package com.jay.serializer;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

/**
 * Kryo 序列化器
 * 提供对象与字节流之间的相互转换，使用 Kryo 库进行高效序列化和反序列化
 */
public class KryoSerializer implements Serializer {
    /**
     * kryo 线程不安全，使用 ThreadLocal 保证每个线程只有一个 Kryo
     * 这样做可以避免在多线程环境下的并发问题
     */
    private static final ThreadLocal<Kryo> KRYO_THREAD_LOCAL = ThreadLocal.withInitial(() -> {
        Kryo kryo = new Kryo();
        // 设置动态动态序列化和反序列化类，不提前注册所有类（可能有安全问题）
        // 这允许 Kryo 处理未提前注册的类，但可能会影响性能和安全性
        kryo.setRegistrationRequired(false);
        return kryo;
    });

    @Override
    public <T> byte[] serialize(T obj) {
        // 使用 ByteArrayOutputStream 和 Kryo 的 Output 对象进行序列化
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        Output output = new Output(byteArrayOutputStream);
        // 获取当前线程的 Kryo 实例并写入对象
        KRYO_THREAD_LOCAL.get().writeObject(output, obj);
        output.close();
        // 返回序列化后的字节流
        return byteArrayOutputStream.toByteArray();
    }

    @Override
    public <T> T deserialize(byte[] bytes, Class<T> classType) {
        // 使用 ByteArrayInputStream 和 Kryo 的 Input 对象进行反序列化
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        Input input = new Input(byteArrayInputStream);
        // 获取当前线程的 Kryo 实例并读取对象
        T result = KRYO_THREAD_LOCAL.get().readObject(input, classType);
        input.close();
        // 返回反序列化后的对象
        return result;
    }
}
